package com.lizemin.annotation;

import cn.hutool.core.util.ClassUtil;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;

import java.util.Set;

/**
 * 批量将FeignClient的接口代理实例注册到spring容器中
 */
public class FeignClientRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // 将EnableFeignClients注解的属性值转成map
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(EnableFeignClients.class.getName()));
        if (attributes != null) {
            // 拿到注解的值
            String[] basePackages = attributes.getStringArray("basePackages");
            for (String basePackage : basePackages) {
                Set<Class<?>> classes = ClassUtil.scanPackage(basePackage);
                for (Class<?> cl : classes) {
                    Class<?> clazz;
                    try {
                        clazz = Class.forName(cl.getName());
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                    if (clazz.isInterface() && clazz.isAnnotationPresent(FeignClient.class)) {
                        registerFeignClient(registry, clazz);
                    }
                }
            }
        }
    }

    private void registerFeignClient(BeanDefinitionRegistry registry, Class<?> clazz) {
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(FeignClientProxy.class); // 工厂类
        beanDefinition.setFactoryMethodName("getProxy"); //工厂方法，类似于@bean注解标记的方法
        beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(clazz);
        registry.registerBeanDefinition(clazz.getSimpleName(), beanDefinition);
    }
}